package com.vf.admin.client.controller.pay.wxapplet.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vf.admin.client.controller.pay.wxapplet.service.JsApiService;
import com.vf.admin.client.service.AppOrderService;
import com.vf.admin.client.service.VipOrderService;
import com.vf.admin.common.Constants;
import com.vf.admin.miaodong.entity.*;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;

import static com.vf.admin.utils.RandomUtil.getOrderIdByUUId;

/**
 * <p>Title : </p>
 * <p>Description : </p>
 * <p>DevelopTools : IDEA</p>
 * <p>DevelopSystem : Windows11</p>
 *
 * @Author : zxw
 * @Date 2023/11/23 13:39
 */
@Service
public class JsApiServiceImpl implements JsApiService {

    @Resource
    private AppOrderService appOrderService;
    @Resource
    private VipOrderService vipOrderService;

    /**
     * 如果你是使用Apache HttpClient的商户开发者，可以使用它构造HttpClient。得到的HttpClient在执行请求时将自动携带身份认证信息，并检查应答的微信支付签名。
     */
    private static CloseableHttpClient httpClient = null;


    public void initCertificates(WxAppletConfigs wxAppletConfigs) {

        // 加载商户私钥（privateKey：私钥字符串）
        PrivateKey merchantPrivateKey = null;
        merchantPrivateKey = PemUtil
//                .loadPrivateKey(new ByteArrayInputStream(JsApiConstants.PRIVATE_KEY.getBytes(StandardCharsets.UTF_8)));
                .loadPrivateKey(new ByteArrayInputStream(wxAppletConfigs.getPrivateKey().getBytes(StandardCharsets.UTF_8)));

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        AutoUpdateCertificatesVerifier verifier = null;
        verifier = new AutoUpdateCertificatesVerifier(
//                new WechatPay2Credentials(JsApiConstants.MCH_ID, new PrivateKeySigner(JsApiConstants.MCH_SERIAL_NO, merchantPrivateKey)),
//                JsApiConstants.API_V3_KEY.getBytes(StandardCharsets.UTF_8));
                new WechatPay2Credentials(wxAppletConfigs.getMchId(), new PrivateKeySigner(wxAppletConfigs.getMchSerialNo(), merchantPrivateKey)),
                wxAppletConfigs.getApiKey().getBytes(StandardCharsets.UTF_8));

        // 初始化httpClient
        httpClient = WechatPayHttpClientBuilder.create()
//                .withMerchant(JsApiConstants.MCH_ID, JsApiConstants.MCH_SERIAL_NO, merchantPrivateKey)
                .withMerchant(wxAppletConfigs.getMchId(), wxAppletConfigs.getMchSerialNo(), merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();
    }


    public PrivateKey privateKey(WxAppletConfigs wxAppletConfigs) {
        return PemUtil.loadPrivateKey(new ByteArrayInputStream(wxAppletConfigs.getPrivateKey().getBytes(StandardCharsets.UTF_8)));
    }


    @Override
    public Map<String, String> zyJsApiDiamondRecharge(AppUser user, AppCzMoney czMoney, String mobileSpec, String openid,WxAppletConfigs wxAppletConfigs,String appId) {

        //添加订单记录
        AppOrder appOrder = new AppOrder();
        appOrder.setCreatetime(new Date());
        appOrder.setOrdernum(getOrderIdByUUId());//生成订单号
        appOrder.setCzMoneyId(czMoney.getId());
        appOrder.setMoney(BigDecimal.valueOf(czMoney.getMoney()));
        appOrder.setStatus(Constants.dingdan_status_dfk);//默认  1、代付款 2、已付款
        appOrder.setType(Constants.dingdan_zhiFuLeiXing_wx); //订单支付类型  默认 1、支付宝 2、微信 3、苹果  4、杉德支付宝 5、杉德微信
        appOrder.setUserid(user.getId());//下单人信息
        appOrder.setPic(user.getPic());
        appOrder.setNick(user.getNick());
        appOrder.setPhone(user.getLoginname());
        appOrder.setNum(czMoney.getDiamonds().add(czMoney.getGive()));
        appOrder.setMobileSpec(mobileSpec);
        appOrderService.save(appOrder);
        //金额
        int total = appOrder.getMoney().multiply(new BigDecimal(100)).intValue();//单位是分
//                int total = 1;//单位是分

        //初始化连接
        initCertificates(wxAppletConfigs);

        // 请求body参数
        JSONObject order = new JSONObject();
        //应用ID
        order.put("appid", appId);
        //商户号
        order.put("mchid", wxAppletConfigs.getMchId());
        // 商品描述
        order.put("description", "商品购买");
        // 订单号
        order.put("out_trade_no", appOrder.getOrdernum());
        // 通知地址
        order.put("notify_url", wxAppletConfigs.getDiamondNotifyUrl() + "/" + appId + "/" + wxAppletConfigs.getMchId());
        /*订单金额*/
        JSONObject amount = new JSONObject();
        amount.put("total", total);
        // 货币类型
        amount.put("currency", "CNY");
        order.put("amount", amount);
        /*支付者*/
        JSONObject payer = new JSONObject();
        // 用户标识
        payer.put("openid", openid);
        order.put("payer", payer);
        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");
        httpPost.setEntity(new StringEntity(order.toJSONString(), "UTF-8"));
        String signMap = "";
        //完成签名并执行请求
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            try {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
//                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                    signMap = EntityUtils.toString(response.getEntity());
                } else if (statusCode == 204) {
                    System.out.println("success");
                } else {
//                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
                    throw new IOException("request failed");
                }
            } finally {
                response.close();
                httpClient.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = JSON.parseObject(signMap);
        // 时间戳
        String timeStamp = String.valueOf(System.currentTimeMillis());
        // 随机字符串
        String nonceStr = UUID.randomUUID().toString();
        //package
        String prepayId = "prepay_id=" + jsonObject.get("prepay_id");
        //signType
        String signType = "RSA";
        //paySign
        String paySign = null;
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            String sb = appId + "\n" + //小程序appId
                    timeStamp + "\n" + //时间戳
                    nonceStr + "\n" + //随机字符串
                    prepayId + "\n";//订单详情扩展字符串
            // 从证书管理器中获取verifier
            PrivateKey privateKey = privateKey(wxAppletConfigs);
            signature.initSign(privateKey);
            signature.update(sb.getBytes(StandardCharsets.UTF_8));
            paySign = Base64.getEncoder().encodeToString(signature.sign());
        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            e.printStackTrace();
        }
        Map<String, String> map = new HashMap<>();
        map.put("appId", appId);
        map.put("timeStamp", timeStamp);
        map.put("nonceStr", nonceStr);
        map.put("package", prepayId);
        map.put("signType", signType);
        map.put("paySign", paySign);

        return map;
    }

    @Override
    public Map<String, String> zyJsApiOpenVipRecharge(AppUser user, VipPackage vipPackage, String mobileSpec, String openid,WxAppletConfigs wxAppletConfigs,String appId) {

        //添加订单记录
        VipOrder vipOrder = new VipOrder();
        vipOrder.setUserId(user.getId());
        vipOrder.setOrderNo(getOrderIdByUUId());//订单号
        vipOrder.setVipPackageId(vipPackage.getId());//
        vipOrder.setStatus(0);  //0待支付 1已支付
        vipOrder.setPayType("weixinPay");
        vipOrder.setCreateTime(new Date());
        vipOrder.setType(Constants.dingdan_zhiFuLeiXing_wx); //订单支付类型  默认 1、支付宝 2、微信 3、苹果  4、杉德支付宝 5、杉德微信
        vipOrder.setMobileSpec(mobileSpec);
        vipOrder.setNick(user.getNick());
        vipOrder.setPhone(user.getLoginname());
        vipOrder.setPrice(vipPackage.getPrice());
        vipOrder.setPic(user.getPic());
        vipOrder.setMchName(wxAppletConfigs.getRemark());//商户名
        vipOrder.setMchId(wxAppletConfigs.getMchId());//商户ID
        vipOrderService.save(vipOrder);

        //金额
        int total = vipPackage.getPrice().multiply(new BigDecimal(100)).intValue();//单位是分
//        int total = 1;//单位是分
        //初始化连接
        initCertificates(wxAppletConfigs);

        // 请求body参数
        JSONObject order = new JSONObject();
        //应用ID
        order.put("appid", appId);
        //商户号
        order.put("mchid", wxAppletConfigs.getMchId());
        // 商品描述
        order.put("description", "商品购买");
        // 订单号
        order.put("out_trade_no", vipOrder.getOrderNo());
        // 通知地址
        order.put("notify_url", wxAppletConfigs.getVipNotifyUrl() + "/" + appId + "/" + wxAppletConfigs.getMchId());
        /*订单金额*/
        JSONObject amount = new JSONObject();
        amount.put("total", total);
        // 货币类型
        amount.put("currency", "CNY");
        order.put("amount", amount);
        /*支付者*/
        JSONObject payer = new JSONObject();
        // 用户标识
        payer.put("openid", openid);
        order.put("payer", payer);

        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");
        httpPost.setEntity(new StringEntity(order.toJSONString(), "UTF-8"));
        String signMap = "";
        //完成签名并执行请求
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            System.out.println(response);
            try {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
                System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
                    signMap = EntityUtils.toString(response.getEntity());
                } else if (statusCode == 204) {
                    System.out.println("success");
                } else {
                System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
                    throw new IOException("request failed");
                }
            } finally {
                response.close();
                httpClient.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = JSON.parseObject(signMap);
        // 时间戳
        String timeStamp = String.valueOf(System.currentTimeMillis());
        // 随机字符串
        String nonceStr = UUID.randomUUID().toString();
        //package
        String prepayId = "prepay_id=" + jsonObject.get("prepay_id");
        //signType
        String signType = "RSA";
        //paySign
        String paySign = null;
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            String sb = appId + "\n" + //小程序appId
                    timeStamp + "\n" + //时间戳
                    nonceStr + "\n" + //随机字符串
                    prepayId + "\n";//订单详情扩展字符串
            // 从证书管理器中获取verifier
            PrivateKey privateKey = privateKey(wxAppletConfigs);
            signature.initSign(privateKey);
            signature.update(sb.getBytes(StandardCharsets.UTF_8));
            paySign = Base64.getEncoder().encodeToString(signature.sign());
        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            e.printStackTrace();
        }
        Map<String, String> map = new HashMap<>();
        map.put("appId", appId);
        map.put("timeStamp", timeStamp);
        map.put("nonceStr", nonceStr);
        map.put("package", prepayId);
        map.put("signType", signType);
        map.put("paySign", paySign);

        return map;
    }
}
